﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Othello;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace OApp
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private BoardStep currentStep = new BoardStep() { Board = new Board() };
        private Stack<BoardStep> backwordBoards = new Stack<BoardStep>();
        private Stack<BoardStep> forwordBoards = new Stack<BoardStep>();

        private Rectangle[,] squares = new Rectangle[Board.Size, Board.Size];

        public Board CurrentBoard
        {
            get { return currentStep.Board; }
        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < Board.Size; i++)
            {
                for (int j = 0; j < Board.Size; j++)
                {
                    Rectangle rect = new Rectangle() { Width = 40, Height = 40 };
                    rect.SetValue(Canvas.TopProperty, i * 42d);
                    rect.SetValue(Canvas.LeftProperty, j * 42d);
                    squares[i, j] = rect;
                    canvasBorder.Children.Add(rect);
                }
            }

            Reset();
        }

        public void Redraw()
        {
            for (int i = 0; i < Board.Size; i++)
            {
                for (int j = 0; j < Board.Size; j++)
                {
                    squares[i, j].Fill = new SolidColorBrush(GetColorOfPiece(CurrentBoard[i, j]));
                }
            }
            if (currentStep.Point >= 0 && !currentStep.Board.Reversed) squares[currentStep.Point / Board.Size, currentStep.Point % Board.Size].Fill = new SolidColorBrush(Colors.LightGoldenrodYellow);
            labelSelfCount.Content = CurrentBoard.Reversed ? CurrentBoard.OtherCount : CurrentBoard.SelfCount;
            labelOtherCount.Content = CurrentBoard.Reversed ? CurrentBoard.SelfCount : CurrentBoard.OtherCount;
            labelScore.Content = OthelloUtil.GetScore(CurrentBoard);
            if (!CurrentBoard.Reversed)
            {
                labelScore2.Content = currentStep.Score;
                //BoardStep next = OthelloUtil.SeachForNextStep(CurrentBoard);
                //if (next != null)
                //{
                //    squares[next.Point % 8, next.Point / 8].Fill = new SolidColorBrush(Colors.Green);
                //    labelScore2.Content = next.Score;
                //}
            }
        }

        private Color GetColorOfPiece(Piece piece)
        {
            switch (piece)
            {
                case Piece.Moveable: return Colors.Yellow;
                case Piece.Other: return CurrentBoard.Reversed ? Colors.Black : Colors.White;
                case Piece.Self: return CurrentBoard.Reversed ? Colors.White : Colors.Black; ;
                default: return Colors.LightGray;
            }
        }

        private void canvasBorder_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
        {
        }

        private void canvasBorder_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (!CurrentBoard.Reversed)
            {
                Point p = e.GetPosition(canvasBorder);
                int row = (int)p.Y / 42, column = (int)p.X / 42;
                PutDown(row, column);
            }
        }

        private void PutDown(int row, int column)
        {
            if (row >= 0 && row < 8 && column >= 0 && column < 8 && CurrentBoard[row, column] == Piece.Moveable)
            {
                forwordBoards.Clear();
                backwordBoards.Push(currentStep);
                currentStep = new BoardStep() { Board = CurrentBoard.Clone(), Point = row * Board.Size + column };
                CurrentBoard.PutDown(row, column);
                Redraw();
                AsynOtherDown();
            }
        }

        private void AsynOtherDown()
        {
            new Action(OtherDown).BeginInvoke(delegate(IAsyncResult ar)
            {
                canvasBorder.Dispatcher.Invoke(new Action(() =>
                {
                    Redraw();
                    if (CurrentBoard.Finished) MessageBox.Show("End");
                    else if (CurrentBoard.Reversed)
                    {
                        MessageBox.Show("Not position to put");
                        AsynOtherDown();
                    }
                    else if (CurrentBoard.MoveableCount == 0)
                    {
                        CurrentBoard.Reverse();
                        MessageBox.Show("Not position to put");
                        AsynOtherDown();
                    }
                }));

            }, null);
        }

        private void OtherDown()
        {
            if (CurrentBoard.Reversed)
            {
                BoardStep next = OthelloUtil.SeachForNextStep(CurrentBoard);
                if (next != null)
                {
                    forwordBoards.Clear();
                    backwordBoards.Push(currentStep);
                    currentStep = next;
                }
                else
                {
                    CurrentBoard.Reverse();
                }
            }
        }

        private void buttonReset_Click(object sender, RoutedEventArgs e)
        {
            Reset();
        }

        private void Reset()
        {
            forwordBoards.Clear();
            backwordBoards.Clear();
            currentStep.Point = -1;
            CurrentBoard.Initlize();
            Redraw();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            using (FileStream file = File.Open("save.oth", FileMode.Create, FileAccess.Write))
            {
                BinaryFormatter format = new BinaryFormatter();
                format.Serialize(file, currentStep);
            }

            OthelloUtil.SaveScore(CurrentBoard);
        }

        private void buttonBack_Click(object sender, RoutedEventArgs e)
        {
            MoveBackwords();
        }

        private void buttonForword_Click(object sender, RoutedEventArgs e)
        {
            MoveForwords();
        }

        private void MoveBackwords()
        {
            if (backwordBoards.Count > 0)
            {
                do
                {
                    forwordBoards.Push(currentStep);
                    currentStep = backwordBoards.Pop();
                } while (backwordBoards.Count > 0 && CurrentBoard.Reversed);
                Redraw();
            }
        }

        private void MoveForwords()
        {
            if (forwordBoards.Count > 0)
            {
                do
                {
                    backwordBoards.Push(currentStep);
                    currentStep = forwordBoards.Pop();
                } while (forwordBoards.Count > 0 && CurrentBoard.Reversed);
                Redraw();
            }
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            using (FileStream file = File.Open("save.oth", FileMode.Open, FileAccess.Read))
            {
                BinaryFormatter format = new BinaryFormatter();
                currentStep = (BoardStep)format.Deserialize(file);
                forwordBoards.Clear();
                backwordBoards.Clear();
                Redraw();
            }
        }

        private void button3_Click(object sender, RoutedEventArgs e)
        {
            BoardStep step = OthelloUtil.SeachForNextStep(CurrentBoard);
            squares[step.Point / 8, step.Point % 8].Fill = new SolidColorBrush(Colors.Red);
            labelScore2.Content = step.Score;
        }
    }
}
